﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine.Dtd.Schema;
using System.Diagnostics;
using Engine.Sgml.Allocation;
using Engine.Sgml.Merging;

namespace Engine.Sgml.Validation.Rules {
    /// <summary>
    /// Provides a way to create a custom rule in order to check the validity of SGML document structure. 
    /// </summary>
    /// <include file='IValidationRuleDoc.xml' path='document/example'/>
    internal interface IValidationRule {
        /// <summary>
        /// Gets the name of this rule that is equal
        /// to the name of element on which this rule performed. 
        /// </summary>
        SName Name { get; }
        /// <summary>
        /// Instructs a validator to ignore the specified element.
        /// </summary>
        /// <param name="element">An element that maybe ignored.</param>
        /// <param name="ancestor">An ancestor of the specified element.</param>
        /// <returns>true to ignore specified element; otherwise, false.</returns>
        bool Ignore(SElement element, SElement ancestor);
        /// <summary>
        /// Determines whether the specified element contains no content.
        /// </summary>
        /// <param name="element">An element to validate</param>
        /// <returns>true if the element contains no content; otherwise false;</returns>
        bool IsEmpty(SElement element);
        /// <summary>
        /// Determines whether a validator can close the specified element.
        /// </summary>
        /// <param name="element">An element to close.</param>
        /// <param name="endElement">An end element for the closed element.</param>
        /// <returns>true to close element; otherwise, false.</returns>
        bool CanClose(SElement element, SElement endElement);
        /// <summary>
        /// Determines whether the specified ancestor can contain the specified element.
        /// </summary>
        /// <param name="element">An element to validate.</param>
        /// <param name="ancestor">An ancestor that can contain the specified element.</param>
        /// <returns>true if the ancestor can contain the element; otherwise, false.</returns>
        bool CanContain(SElement element, SElement ancestor);
        /// <summary>
        /// Determines whether the specified block can enclosed in some ancestor.
        /// </summary>
        /// <param name="block">An inconsistent block that may be enclosed.</param>
        /// <param name="ancestor">An ancestor where the block will be surrounded.</param>
        /// <returns>true if the block can be surround; otherwise, false.</returns>
        bool CanSurround(InconsistentBlock block, SElement ancestor);
        /// <summary>
        /// Enclose an inconsistent block.
        /// </summary>
        /// <param name="block">An inconsistent block to allocate.</param>
        /// <param name="ancestor">An ancestor where the block will be surrounded.</param>
        /// <returns>true if the block successfully surrounded in one or more ancestors; otherwise, false.</returns>
        bool Surround(InconsistentBlock block, SElement ancestor);
        }
    }
